package com.bonc.modules.rpt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonc.common.utils.DataSourceUtils;
import com.bonc.common.utils.HttpContextUtils;
import com.bonc.common.utils.RedisUtils;
import com.bonc.datasource.annotation.DataSource;
import com.bonc.datasource.config.DynamicContextHolder;
import com.bonc.factory.PageFactory;
import com.bonc.modules.rpt.dao.DynamicColumnDao;
import com.bonc.modules.rpt.dao.DynamicDao;
import com.bonc.modules.rpt.dao.UserColumnDao;
import com.bonc.modules.rpt.entity.ColumnEntity;
import com.bonc.modules.rpt.entity.DynamicColumnEntity;
import com.bonc.modules.rpt.entity.UserColumnEntity;
import com.bonc.modules.rpt.param.FixParam;
import com.bonc.modules.rpt.param.UserColumnParam;
import com.bonc.modules.rpt.result.DynamicColumnResult;
import com.bonc.modules.rpt.service.DynamicService;
import com.bonc.modules.sys.entity.SysUserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bonc.modules.sys.service.impl.SysUserTokenServiceImpl.USER_TOKEN_KEY_PREFIX;

/**
 * @author jinlong
 * @date 2021/7/20
 */
@Service
public class DynamicServiceImpl extends ServiceImpl<UserColumnDao, UserColumnEntity> implements DynamicService {


    @Autowired
    @Qualifier("data")
    private javax.sql.DataSource dataSource;

    @Autowired
    private RedisUtils redisUtils;


    @Autowired
    private DynamicColumnDao dynamicColumnDao;

    @Autowired
    private DynamicDao dynamicDao;


    @Override
    public List<DynamicColumnResult> getConfigTableColumns(String tableName) {
        LambdaQueryWrapper<DynamicColumnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DynamicColumnEntity::getTableName, tableName);
        List<DynamicColumnEntity> dynamicColumnEntities = dynamicColumnDao.selectList(queryWrapper);
        Map<String, String> tableMeta = getTableMeta(tableName);
        if (ObjectUtil.isNotEmpty(dynamicColumnEntities)) {
            return this.columnCheck(dynamicColumnEntities, tableMeta);
        }
        return tableMeta.entrySet().stream().map(entry -> {
            DynamicColumnResult dynamicColumnResult = new DynamicColumnResult();
            dynamicColumnResult.setTableName(tableName);
            dynamicColumnResult.setColumnName(entry.getKey());
            dynamicColumnResult.setColumnDesc(entry.getValue());
            return dynamicColumnResult;
        }).collect(Collectors.toList());
    }


    @Override
    public List<DynamicColumnResult> getDefaultTableColumns(String tableName) {
        LambdaQueryWrapper<DynamicColumnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DynamicColumnEntity::getTableName, tableName);
        queryWrapper.eq(DynamicColumnEntity::getIsDefault, true);
        List<DynamicColumnEntity> defaultColumn = dynamicColumnDao.selectList(queryWrapper);
        Map<String, String> tableMeta = getTableMeta(tableName);
        return this.columnCheck(defaultColumn, tableMeta);

    }

    @Override
    public List<DynamicColumnResult> getUserColumn(String tableName) {
        String token = HttpContextUtils.getToken();
        SysUserEntity userEntity = redisUtils.get(USER_TOKEN_KEY_PREFIX + token, SysUserEntity.class);
        LambdaQueryWrapper<UserColumnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserColumnEntity::getUserId, userEntity.getUserId());
        queryWrapper.eq(UserColumnEntity::getTableName, tableName);
        List<UserColumnEntity> userColumnEntityList = this.baseMapper.selectList(queryWrapper);
        Map<String, String> tableMeta = this.getTableMeta(tableName);

        return this.columnCheck(userColumnEntityList, tableMeta);
    }

    @Override
    public boolean modifyUserColumn(UserColumnParam userColumnParam) {
        LambdaQueryWrapper<UserColumnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserColumnEntity::getTableName, userColumnParam.getTableName());

        String token = HttpContextUtils.getToken();
        SysUserEntity userEntity = redisUtils.get(USER_TOKEN_KEY_PREFIX + token, SysUserEntity.class);

        //删除
        queryWrapper.eq(UserColumnEntity::getUserId, userEntity.getUserId());
        this.remove(queryWrapper);

        //保存
        List<UserColumnEntity> entityList = CollUtil.newArrayList();

        if (ObjectUtil.isNotNull(userColumnParam) && ObjectUtil.isNotEmpty(userColumnParam.getColumns())) {
            String columns = userColumnParam.getColumns();
            String[] columnArr = columns.split(",");
            for (int i = 0; i < columnArr.length; i++) {
                UserColumnEntity userColumnEntity = new UserColumnEntity();
                userColumnEntity.setUserId(userEntity.getUserId());
                userColumnEntity.setTableName(userColumnParam.getTableName());
                userColumnEntity.setColumnName(columnArr[i]);
                userColumnEntity.setCreateTime(new Date());
                userColumnEntity.setUpdateTime(new Date());
                entityList.add(userColumnEntity);
            }

        }

        return this.saveOrUpdateBatch(entityList);
    }

    @Override
    @DataSource("data")
    public String getMaxDate(String tableName) {
        return dynamicDao.selectMaxDate(tableName);
    }

    @Override
    @DataSource("data")
    public Page queryPage(FixParam fixParam) {
        return this.dynamicDao.selectPage(PageFactory.defaultPage(), fixParam);
    }

    @Override
    @DataSource("data")
    public List queryData(FixParam fixParam) {
        return this.dynamicDao.selectList(fixParam);
    }

    public Map<String, String> getTableMeta(String tableName) {
        Map<String, String> columns = null;
        Connection connection = null;
        try {
//            DynamicContextHolder.push("data");
            connection = dataSource.getConnection();
            columns = DataSourceUtils.getColumns(connection, tableName);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return columns;
    }

    private List<DynamicColumnResult> columnCheck(List<? extends ColumnEntity> columnEntities, Map<String, String> tableMeta) {
        List<DynamicColumnResult> resultList = CollUtil.newArrayList();
        for (ColumnEntity columnEntity : columnEntities) {
            String remark = MapUtil.getStr(tableMeta, columnEntity.getColumnName());

            if (ObjectUtil.isNotNull(tableMeta)) {
                if (MapUtil.getStr(tableMeta, columnEntity.getColumnName()) == null) {
                    continue;
                }
            }

            DynamicColumnResult dynamicColumnResult = new DynamicColumnResult();
            BeanUtil.copyProperties(columnEntity, dynamicColumnResult);
            dynamicColumnResult.setColumnDesc(remark);
            resultList.add(dynamicColumnResult);
        }

        return resultList;
    }

}
